package juc.cas;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/*
* cas 保证线程安全 -悲观锁机制
* */
public class Test6 {
    public static void main(String[] args) {
        Account account1 = new UnsafeImpl(1000000);
        account1.demo();
        System.out.println(account1.getBalance());

        Account account2 = new SafeImpl(1000000);
        account2.demo();
        System.out.println(account2.getBalance());

        Account account3 = new SafeImpl1(1000000);
        account3.demo();
        System.out.println(account3.getBalance());

    }
}
class SafeImpl1 implements Account{//cas
    private AtomicInteger balance;

    public SafeImpl1(int balance) {
        this.balance=new AtomicInteger(balance);
    }

    @Override
    public int getBalance() {
        return balance.get();
    }

    @Override
    public void saveMoney(int money) {
          /* while (true){
               int temp = balance.get();
               if (balance.compareAndSet(temp,temp+money)) {
                   break;
               }
           }*/
          balance.addAndGet(money);
    }
}
class SafeImpl implements Account{
    private int balance;

    public SafeImpl(int balance) {
        this.balance = balance;
    }

    @Override
    public synchronized int getBalance() {
        return balance;
    }

    @Override
    public synchronized void saveMoney(int money) {
          balance+=money;
    }
}
class UnsafeImpl implements Account{
    private int balance;

    public UnsafeImpl(int balance) {
        this.balance = balance;
    }

    @Override
    public int getBalance() {
        return balance;
    }

    @Override
    public void saveMoney(int money) {
          balance+=money;
    }
}
interface Account{
    int getBalance();
    void saveMoney(int money);
     default void demo(){
         List<Thread>threads=new ArrayList<>();
         long start=System.currentTimeMillis();
         for (int i = 0; i <1000 ; i++) {
             Thread t = new Thread(() -> {
                 for (int j = 0; j <100 ; j++) {
                     saveMoney(-10);
                 }
             });
             t.start();
             threads.add(t);
         }
         for (Thread thread : threads) {
             try {
                 thread.join();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
         long end=System.currentTimeMillis();
         System.out.println("take:"+(end-start)+"ms");
    }
}
